package com.xnyzc.lhy.statistics.service.impl.capacity;

import com.xnyzc.lhy.common.constant.RedisPrefixConstant;
import com.xnyzc.lhy.common.entity.Rv;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.order.EOrderStatus;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.DateUtil;
import com.xnyzc.lhy.statistics.eenum.EOrderChart;
import com.xnyzc.lhy.statistics.eenum.EOrderOption;
import com.xnyzc.lhy.statistics.entity.param.capacity.CapacityParam;
import com.xnyzc.lhy.statistics.entity.result.capacity.OrderHistogramResult;
import com.xnyzc.lhy.statistics.entity.result.capacity.OrderResult;
import com.xnyzc.lhy.statistics.entity.result.capacity.TransportCapacityLineChart;
import com.xnyzc.lhy.statistics.mapper.statistics.CollectCapacityStatisticalMapper;
import com.xnyzc.lhy.statistics.service.capacity.CapacityService;
import com.xnyzc.lhy.statistics.service.capacity.OrderSummaryService;
import com.xnyzc.lhy.statistics.service.search.OrderSearchService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Slf4j
@Service
public class OrderSummaryServiceImpl implements OrderSummaryService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private CapacityService capacityService;

    @Autowired
    private CollectCapacityStatisticalMapper collectCapacityStatisticalMapper;

    @Autowired
    private OrderSearchService orderSearchService;

    @Override
    public Rv getSummaryResult(CapacityParam capacityParam) {

        List<OrderResult> orderResults = new ArrayList<>();

        // 今日订单流水
        orderResults.add(this.orderFlowToDay(capacityParam));

        // 今日乘客发单量
        OrderResult orderResult = this.userBillCountToDay(capacityParam);
        orderResults.add(orderResult);

        // 今日应答订单量
        orderResults.add(this.driverReplyCountToDay(capacityParam));

        // 今日完成订单量
        orderResults.add(this.driverCompleteCountToDay(capacityParam));

        // 今日询价乘客数
        orderResults.add(this.enquiry(capacityParam));

        Map<String, List> resultMap = new HashMap<>(2);
        resultMap.put("orderData", orderResults);

        return Rv.wrap(resultMap);
    }

    @Override
    public Rv getSummaryStatistical(CapacityParam capacityParam) {

        // 今日乘客发单量
        OrderResult orderResult = this.userBillCountToDay(capacityParam);

        List<OrderHistogramResult> orderChartResults = new ArrayList<>();
        List<String> title = new ArrayList<>();

        // 应答前乘客其他平台受理订单
        this.summaryOrderData(orderChartResults, this.priorOtherAcceptance(capacityParam), orderResult.getValue());
        // 调度超时订单
        this.summaryOrderData(orderChartResults, this.dispatchingTimeout(capacityParam), orderResult.getValue());
        // 应答前乘客取消量
        this.summaryOrderData(orderChartResults, this.afterCancellation(capacityParam), orderResult.getValue());
        // 应答后其他平台受理订单
        this.summaryOrderData(orderChartResults, this.afterOtherAcceptance(capacityParam), orderResult.getValue());
        // 应答后司机取消订单量
        this.summaryOrderData(orderChartResults, this.afterDriverCancel(capacityParam), orderResult.getValue());
        // 应答后乘客取消订单量
        this.summaryOrderData(orderChartResults, this.rearPassengerCancellation(capacityParam), orderResult.getValue());
        // 客服取消订单量
        this.summaryOrderData(orderChartResults, this.serviceCancellation(capacityParam), orderResult.getValue());
        // 履行中订单量
        this.summaryOrderData(orderChartResults, this.inPerformance(capacityParam), orderResult.getValue());
        // 待支付订单量
        this.summaryOrderData(orderChartResults, this.toBePaid(capacityParam), orderResult.getValue());
        // 已支付乘客取消量
        this.summaryOrderData(orderChartResults, this.paidPassengerCancellation(capacityParam), orderResult.getValue());

        // 降序
        this.sortOrderResult(orderChartResults, title);

        Map<String, List> resultMap = new HashMap<>(2);
        resultMap.put("orderHistogram", orderChartResults);
        resultMap.put("orderTitle", title);

        return Rv.wrap(resultMap);
    }

    /**
     * 获取订单折线集
     * @param capacityParam
     * @return
     */
    @Override
    public Rv getHistorySummaryStatistical(CapacityParam capacityParam) {
        if (CheckUtil.objIsEmpty(capacityParam)) {
            throw PangException.create(EErrorCode.missingArg);
        }

        Integer type = capacityService.chartType(capacityParam.getTimeList());
        capacityParam.setChartType(type);

        TransportCapacityLineChart transportCapacityLineChart = null;

        try {
            transportCapacityLineChart = new TransportCapacityLineChart(capacityParam.getTimeList().get(0), capacityParam.getChartType(), DateUtil.dateSubtractDay(capacityParam.getTimeList().get(0).getTime(), capacityParam.getTimeList().get(1).getTime()));
        } catch (Exception e) {
            throw PangException.create(EErrorCode.missingArg);
        }

        switch (capacityParam.getCapacityType()) {
            case 1:
                // 订单流水
                transportCapacityLineChart = this.orderFlowToDayChart(transportCapacityLineChart, capacityParam);
                break;
            case 2:
                // 乘客发单量
                transportCapacityLineChart = this.userBillCountToDayChart(transportCapacityLineChart, capacityParam);
                break;
            case 3:
                // 平台应答量
                transportCapacityLineChart = this.driverReplyCountToDayChart(transportCapacityLineChart, capacityParam);
                break;
            case 4:
                // 完成订单量
                transportCapacityLineChart = this.driverCompleteCountToDayChart(transportCapacityLineChart, capacityParam);
                break;
            case 5:
                // 平台完单率
                transportCapacityLineChart = this.driverCompleteCountPropChart(transportCapacityLineChart, capacityParam);
                break;
            default:
                throw PangException.create(EErrorCode.mainType);
        }

        transportCapacityLineChart.setName(EOrderOption.value(capacityParam.getCapacityType()));

        return Rv.wrap(transportCapacityLineChart);
    }

    /**
     * 今日订单流水
     * @return OrderResult
     */
    private OrderResult orderFlowToDay(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        BigDecimal account = collectCapacityStatisticalMapper.orderFlow(capacityParam);
        // Double account = orderSearchService.orderFlowToDay(capacityParam);
        orderResult.setName(EOrderChart.ORDER_FLOW.getValue());
        orderResult.setValue(this.convertToStringAsCapacityCount(account));
        return orderResult;
    }

    /**
     * 今日乘客发单量
     * @return OrderResult
     */
    private OrderResult userBillCountToDay(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.userBillCount(capacityParam);
        // Integer account = orderSearchService.userBillCountToDay(capacityParam);
        orderResult.setName(EOrderChart.PASSENGER_INVOICE.getValue());
        orderResult.setValue(this.convertToStringAsCapacityCount(account));
        return orderResult;
    }

    /**
     * 今日应答订单量
     * @return OrderResult
     */
    private OrderResult driverReplyCountToDay(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.driverReplyCount(capacityParam);
        // Integer account = orderSearchService.driverReplyCountToDay(capacityParam);
        orderResult.setName(EOrderChart.ANSWER_ORDER.getValue());
        orderResult.setValue(this.convertToStringAsCapacityCount(account));
        return orderResult;
    }

    /**
     * 今日完成订单量
     * @return OrderResult
     */
    private OrderResult driverCompleteCountToDay(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.driverCompleteCount(capacityParam);
        // Integer account = orderSearchService.driverCompleteCountToDay(capacityParam);
        orderResult.setName(EOrderChart.ORDER_FULFILLMENT.getValue());
        orderResult.setValue(this.convertToStringAsCapacityCount(account));
        return orderResult;
    }

    /**
     * 询价乘客数（今日）
     */
    private OrderResult enquiry(CapacityParam capacityParam) {
        // 询价乘客数(今日)
        int count = 0;

        try {
            if (CheckUtil.objIsNotEmpty(capacityParam.getCityId())) {
                Object enquiryCount = redisTemplate.opsForHash().get(RedisPrefixConstant.DIDI_ESTIMATE_NUMBER, capacityParam.getCityId());
                if (CheckUtil.objIsNotEmpty(enquiryCount)) {
                    count = (int) enquiryCount;
                }
            } else {
                Map<String, Object> map = redisTemplate.opsForHash().entries(RedisPrefixConstant.DIDI_ESTIMATE_NUMBER);
                if (CheckUtil.mapIsNotEmpty(map)) {
                    Set<Map.Entry<String, Object>> entries = map.entrySet();

                    for (Map.Entry<String, Object> ele : entries) {
                        count += (int) ele.getValue();
                    }
                }
            }
        } catch (Exception e) {
            log.error("{}", e);
        }

        OrderResult orderResult = new OrderResult();
        orderResult.setName(EOrderChart.ENQUIRY.getValue());
        orderResult.setValue(this.convertToStringAsCapacityCount(count));
        return orderResult;
    }

    /**
     * 应答前乘客其他平台受理订单
     */
    private OrderResult priorOtherAcceptance(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.priorOtherAcceptance(capacityParam);
        // Integer account = orderSearchService.priorOtherAcceptance(capacityParam);
        orderResult.setName(EOrderChart.PRIOR_OTHER_ACCEPTANCE.getValue());
        orderResult.setValue(this.convertToStringAsCount(account));
        return orderResult;
    }

    /**
     * 应答后其他平台受理订单
     */
    private OrderResult afterOtherAcceptance(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.priorOtherAcceptanceAfter(capacityParam);
        // Integer account = orderSearchService.priorOtherAcceptanceAfter(capacityParam);
        orderResult.setName(EOrderChart.AFTER_OTHER_ACCEPTANCE.getValue());
        orderResult.setValue(this.convertToStringAsCount(account));
        return orderResult;
    }

    /**
     * 调度超时订单
     */
    private OrderResult dispatchingTimeout(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.getOrderSummaryByOrderStatus(EOrderStatus.orderTimeout.getType(), capacityParam.getCityId());
        // Integer account = orderSearchService.getOrderSummaryByOrderStatus(capacityParam);
        orderResult.setName(EOrderChart.DISPATCHING_TIMEOUT.getValue());
        orderResult.setValue(this.convertToStringAsCount(account));
        return orderResult;
    }

    /**
     * 应答前乘客取消量
     */
    private OrderResult afterCancellation(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.getOrderSummaryByOrderStatus(EOrderStatus.cancelOrdersFeesPaid.getType(), capacityParam.getCityId());
        // Integer account = orderSearchService.afterCancellation(capacityParam);
        orderResult.setName(EOrderChart.AFTER_CANCELLATION.getValue());
        orderResult.setValue(this.convertToStringAsCount(account));
        return orderResult;
    }

    /**
     * 应答后司机取消订单量
     */
    private OrderResult afterDriverCancel(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.getOrderSummaryByOrderStatus(EOrderStatus.driverCancelOrder.getType(), capacityParam.getCityId());
        // Integer account = orderSearchService.afterDriverCancel(capacityParam);
        orderResult.setName(EOrderChart.AFTER_DRIVER_CANCEL.getValue());
        orderResult.setValue(this.convertToStringAsCount(account));
        return orderResult;
    }

    /**
     * 应答后乘客取消订单量
     */
    private OrderResult rearPassengerCancellation(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.getOrderSummaryByOrderStatus(EOrderStatus.cancelOrderNoNeedPayment.getType(), capacityParam.getCityId());
        // Integer account = orderSearchService.rearPassengerCancellation(capacityParam);
        orderResult.setName(EOrderChart.REAR_PASSENGER_CANCELLATION.getValue());
        orderResult.setValue(this.convertToStringAsCount(account));
        return orderResult;
    }

    /**
     * 客服取消订单量
     */
    private OrderResult serviceCancellation(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.getOrderSummaryByOrderStatus(EOrderStatus.reassigned.getType(), capacityParam.getCityId());
        // Integer account = orderSearchService.serviceCancellation(capacityParam);
        orderResult.setName(EOrderChart.SERVICE_CANCELLATION.getValue());
        orderResult.setValue(this.convertToStringAsCount(account));
        return orderResult;
    }

    /**
     * 履行中订单量
     */
    private OrderResult inPerformance(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.getOrderSummaryByOrderStatus(EOrderStatus.duringTrip.getType(), capacityParam.getCityId());
        // Integer account = orderSearchService.inPerformance(capacityParam);
        orderResult.setName(EOrderChart.IN_PERFROMANCE.getValue());
        orderResult.setValue(this.convertToStringAsCount(account));
        return orderResult;
    }

    /**
     * 待支付订单量
     */
    private OrderResult toBePaid(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.toBePaid(capacityParam);
        // Integer account = orderSearchService.toBePaid(capacityParam);
        orderResult.setName(EOrderChart.TO_BE_PAID.getValue());
        orderResult.setValue(this.convertToStringAsCount(account));
        return orderResult;
    }

    /**
     * 已支付订单量
     */
    private OrderResult paidPassengerCancellation(CapacityParam capacityParam) {
        OrderResult orderResult = new OrderResult();
        Integer account = collectCapacityStatisticalMapper.getOrderSummaryByOrderStatus(EOrderStatus.paymented.getType(), capacityParam.getCityId());
        // Integer account = orderSearchService.paidPassengerCancellation(capacityParam);
        orderResult.setName(EOrderChart.PAID_PASSENGER_CANCELLATION.getValue());
        orderResult.setValue(this.convertToStringAsCount(account));
        return orderResult;
    }

    /**
     * 订单数据汇总
     */
    private void summaryOrderData(List<OrderHistogramResult> arr, OrderResult orderResult, String userBill) {

        OrderHistogramResult orderHistogramResult = new OrderHistogramResult();
        orderHistogramResult.setName(orderResult.getName());
        List<String> list = new ArrayList<>();
        list.add(orderResult.getValue());
        orderHistogramResult.setData(list);

        if (!("0".equals(orderResult.getValue()))) {
            if (!("0".equals(userBill))) {
                Double result = (Double.valueOf(orderResult.getValue()) / Double.valueOf(userBill));
                if (result == 0) {
                    orderHistogramResult.setProportion("0");
                } else {
                    String prop = String.valueOf(result * 100);
                    orderHistogramResult.setProportion(prop.substring(0, prop.indexOf('.') + 2));
                }
            } else {
                orderHistogramResult.setProportion("0");
            }
        } else {
            orderHistogramResult.setProportion("0");
        }

        arr.add(orderHistogramResult);

    }

    /**
     * 汇总数据格式处理
     */
    private String convertToStringAsCount(Object count) {

        if (CheckUtil.objIsNotEmpty(count)) {
            return count.toString();
        } else {
            return "";
        }

    }
    private String convertToStringAsCapacityCount(Object count) {

        if (CheckUtil.objIsNotEmpty(count)) {
            return count.toString();
        } else {
            return "0";
        }

    }

    /**
     * 订单流水折线集
     */
    @Override
    public TransportCapacityLineChart orderFlowToDayChart(TransportCapacityLineChart transportCapacityLineChart, CapacityParam capacityParam) {
        Integer select = capacityParam.getChartType();
        List<Map<String, Object>> resultMap = new ArrayList<>();

        switch (select) {
            case 1:
                // 30 日制订单流水
                resultMap = collectCapacityStatisticalMapper.orderFlowChart(capacityParam.getTimeList(), capacityParam.getCityId());
                break;
            case 2:
                // 7 日制订单流水
                resultMap = collectCapacityStatisticalMapper.orderFlowChart(capacityParam.getTimeList(), capacityParam.getCityId());
                break;
            case 3:
                // 24 时制订单流水
                resultMap = collectCapacityStatisticalMapper.orderFlowToDayChart(capacityParam.getTimeList(), capacityParam.getCityId());
                break;
            default:
                throw PangException.create(EErrorCode.mainType);
        }

        // 汇总结果集
        return capacityService.summary(transportCapacityLineChart, resultMap);
    }

    /**
     * 乘客发单量折线集
     */
    private TransportCapacityLineChart userBillCountToDayChart(TransportCapacityLineChart transportCapacityLineChart, CapacityParam capacityParam) {
        Integer select = capacityParam.getChartType();
        List<Map<String, Object>> resultMap = new ArrayList<>();

        switch (select) {
            case 1:
                // 30 日制乘客发单量
                resultMap = collectCapacityStatisticalMapper.userBillCountChart(capacityParam.getTimeList(), capacityParam.getCityId());
                break;
            case 2:
                // 7 日制乘客发单量
                resultMap = collectCapacityStatisticalMapper.userBillCountChart(capacityParam.getTimeList(), capacityParam.getCityId());
                break;
            case 3:
                // 24 时制乘客发单量
                resultMap = collectCapacityStatisticalMapper.userBillCountToDayChart(capacityParam.getTimeList(), capacityParam.getCityId());
                break;
            default:
                throw PangException.create(EErrorCode.mainType);
        }

        // 汇总结果集
        return capacityService.summary(transportCapacityLineChart, resultMap);
    }

    /**
     * 平台应答量折线图
     */
    private TransportCapacityLineChart driverReplyCountToDayChart(TransportCapacityLineChart transportCapacityLineChart, CapacityParam capacityParam) {
        Integer select = capacityParam.getChartType();
        List<Map<String, Object>> resultMap = new ArrayList<>();

        switch (select) {
            case 1:
                // 30 日制平台应答量
                resultMap = collectCapacityStatisticalMapper.driverReplyCountChart(capacityParam.getTimeList(), capacityParam.getCityId());
                break;
            case 2:
                // 7 日制平台应答量
                resultMap = collectCapacityStatisticalMapper.driverReplyCountChart(capacityParam.getTimeList(), capacityParam.getCityId());
                break;
            case 3:
                // 24 时制平台应答量
                resultMap = collectCapacityStatisticalMapper.driverReplyCountToDayChart(capacityParam.getTimeList(), capacityParam.getCityId());
                break;
            default:
                throw PangException.create(EErrorCode.mainType);
        }

        // 汇总结果集
        return capacityService.summary(transportCapacityLineChart, resultMap);
    }

    /**
     * 平台完单量折线图
     */
    private TransportCapacityLineChart driverCompleteCountToDayChart(TransportCapacityLineChart transportCapacityLineChart, CapacityParam capacityParam) {
        Integer select = capacityParam.getChartType();
        List<Map<String, Object>> resultMap = new ArrayList<>();

        switch (select) {
            case 1:
                // 30 日制平台完单量
                resultMap = collectCapacityStatisticalMapper.driverCompleteCountChart(capacityParam.getTimeList(), capacityParam.getCityId());
                break;
            case 2:
                // 7 日制平台完单量
                resultMap = collectCapacityStatisticalMapper.driverCompleteCountChart(capacityParam.getTimeList(), capacityParam.getCityId());
                break;
            case 3:
                // 24 时制平台完单量
                resultMap = collectCapacityStatisticalMapper.driverCompleteCountToDayChart(capacityParam.getTimeList(), capacityParam.getCityId());
                break;
            default:
                throw PangException.create(EErrorCode.mainType);
        }

        // 汇总结果集
        return capacityService.summary(transportCapacityLineChart, resultMap);
    }

    /**
     * 平台完单率折线图
     */
    private TransportCapacityLineChart driverCompleteCountPropChart(TransportCapacityLineChart transportCapacityLineChart, CapacityParam capacityParam) {

        TransportCapacityLineChart driverCompleteCountProp = this.driverCompleteCountToDayChart(transportCapacityLineChart, capacityParam);

        return this.driverCompleteCountPropCalculation(transportCapacityLineChart, driverCompleteCountProp, capacityParam);

    }

    /**
     * 平台完单率计算
     * @param capacityParam
     * @return
     */
    private TransportCapacityLineChart driverCompleteCountPropCalculation(TransportCapacityLineChart transportCapacityLineChart, TransportCapacityLineChart driverCompleteCountProp, CapacityParam capacityParam) {

        TransportCapacityLineChart driverCompleteProp = transportCapacityLineChart = new TransportCapacityLineChart(capacityParam.getTimeList().get(0), capacityParam.getChartType(), DateUtil.dateSubtractDay(capacityParam.getTimeList().get(0).getTime(), capacityParam.getTimeList().get(1).getTime()));

        List<BigDecimal> driverCompleteList = new ArrayList<>();

        TransportCapacityLineChart userBillCount = this.userBillCountToDayChart(transportCapacityLineChart, capacityParam);

        for (int i = 0; i < userBillCount.getGranularity().size(); i++) {
            // 用户发单量
            BigDecimal userBill = userBillCount.getCollection().get(i);
            // 司机完单量
            BigDecimal driverComplete = driverCompleteCountProp.getCollection().get(i);

            BigDecimal zero = BigDecimal.valueOf(0.00);

            if (userBill.compareTo(zero) != 0 && driverComplete.compareTo(zero) != 0) {
                BigDecimal divideResult = driverComplete.divide(userBill, 2, BigDecimal.ROUND_HALF_UP);
                if (divideResult.compareTo(zero) == 1) {
                    driverCompleteList.add(divideResult.multiply(new BigDecimal(100)));
                } else {
                    driverCompleteList.add(divideResult);
                }
            } else {
                driverCompleteList.add(zero);
            }

        }

        driverCompleteProp.setCollection(driverCompleteList);

        return driverCompleteProp;

    }

    /**
     * 柱状图排序
     */
    private void sortOrderResult(List<OrderHistogramResult> orderChartResults, List<String> title) {

        Collections.sort(orderChartResults, new Comparator<OrderHistogramResult>() {
            @Override
            public int compare(OrderHistogramResult o1, OrderHistogramResult o2) {
                if (Integer.parseInt(o1.getData().get(0)) > Integer.parseInt(o2.getData().get(0))) {
                    return 1;
                }
                if (o1.getData().get(0).equals(o2.getData().get(0))) {
                    return 0;
                }
                return -1;
            }
        });

        for (OrderHistogramResult orderHistogramResult : orderChartResults) {
            title.add(orderHistogramResult.getName());
        }

    }

}
